#include "TcpConnection.h"
#include <sstream>
#include <iostream>
#include "EventLoop.h"

using std::cout;
using std::endl;
using std::ostringstream;

TcpConnection::TcpConnection(int fd, EventLoop &loop)
    : _SocketIO(fd),
      _sock(fd),
      _localAddr(getLocalAddr()),
      _peerAddr(getPeerAddr()),
      _loop(loop)
{
}

TcpConnection::~TcpConnection()
{
}

void TcpConnection::send(const string &msg)
{
    _SocketIO.writen(msg.c_str(), msg.size());
}

string TcpConnection::receive()
{
    char buff[65535] = {0};
    _SocketIO.readLine(buff, sizeof(buff));
    return string(buff);
}

void TcpConnection::setNewConnectionCB(TcpConnectionCB &NewConnectionCB)
{
    if (NewConnectionCB)
    {
        _NewConnectionCB = NewConnectionCB;
    }
}

void TcpConnection::setMessageCB(TcpConnectionCB &MessageCB)
{
    if (MessageCB)
    {
        _MessageCB = MessageCB;
    }
}

void TcpConnection::setCloseCB(TcpConnectionCB &CloseCB)
{
    if (CloseCB)
    {
        _CloseCB = CloseCB;
    }
}

void TcpConnection::handleNewConnectionCB()
{
    if (_NewConnectionCB)
    {
        _NewConnectionCB(shared_from_this());
    }
}

void TcpConnection::handleMessageCB()
{
    if (_MessageCB)
    {
        _MessageCB(shared_from_this());
    }
}

void TcpConnection::handleCloseCB()
{
    if (_CloseCB)
    {
        _CloseCB(shared_from_this());
    }
}

bool TcpConnection::isClose()
{
    char buf[10] = {0};
    int ret = recv(_sock.getFd(), buf, sizeof(buf), MSG_PEEK);
    return 0 == ret;
}

void TcpConnection::sendInLoop(const string &msg)
{
    _loop.addPendingCB(bind(&TcpConnection::send, this, msg));
}
/*------------------------------------------------------------------------*/
string TcpConnection::toString()
{
    ostringstream oss;
    oss << _localAddr.getIp() << ":"
        << _localAddr.getPort() << "---->"
        << _peerAddr.getIp() << ":"
        << _peerAddr.getPort();

    return oss.str();
}

// 获取本端的网络地址信息
InetAddress TcpConnection::getLocalAddr()
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(struct sockaddr);
    // 获取本端地址的函数getsockname
    int ret = getsockname(_sock.getFd(), (struct sockaddr *)&addr, &len);
    if (-1 == ret)
    {
        perror("getsockname");
    }

    return InetAddress(addr);
}

// 获取对端的网络地址信息
InetAddress TcpConnection::getPeerAddr()
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(struct sockaddr);
    // 获取对端地址的函数getpeername
    int ret = getpeername(_sock.getFd(), (struct sockaddr *)&addr, &len);
    if (-1 == ret)
    {
        perror("getpeername");
    }

    return InetAddress(addr);
}
